/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

package org.apache.jmeter.protocol.ldap.sampler;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;

import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

/**
 * Ldap Client class is main class to create, modify, search and delete all the
 * LDAP functionality available.
 * 
 */
public class LdapClient {
	private static final Logger log = LoggingManager.getLoggerForClass();

	private DirContext dirContext = null;

	/**
	 * Constructor for the LdapClient object.
	 */
	public LdapClient() {
	}

	/**
	 * Connect to server.
	 */
	public void connect(String host, String port, String rootdn, String username, String password)
			throws NamingException {
		Hashtable env = new Hashtable();
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); //$NON-NLS-1$
		env.put(Context.PROVIDER_URL, "ldap://" + host + ":" + port + "/" + rootdn); //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$
		env.put(Context.REFERRAL, "throw"); //$NON-NLS-1$
		env.put(Context.SECURITY_CREDENTIALS, password);
		env.put(Context.SECURITY_PRINCIPAL, username);
		dirContext = new InitialDirContext(env);
	}

	/**
	 * Disconnect from the server.
	 */
	public void disconnect() {
		try {
			if (dirContext != null) {
				dirContext.close();
				dirContext = null;
			}
		} catch (NamingException e) {
			log.error("Ldap client - ", e);
		}
	}

	/**
	 * Filter the data in the ldap directory for the given search base.
	 * 
	 * @param searchBase
	 *            where the search should start
	 * @param searchFilter
	 *            filter this value from the base
	 */
	public boolean searchTest(String searchBase, String searchFilter) throws NamingException {
		// System.out.println("Base="+searchBase+" Filter="+searchFilter);
		SearchControls searchcontrols = new SearchControls(SearchControls.SUBTREE_SCOPE, 
				1L, // count limit
				0, // time limit
				null,// attributes (null = all)
				false,// return object ?
				false);// dereference links?
		NamingEnumeration ne = dirContext.search(searchBase, searchFilter, searchcontrols);
		// System.out.println("Loop "+ne.toString()+" "+ne.hasMore());
		// while (ne.hasMore()){
		// Object tmp = ne.next();
		// System.out.println(tmp.getClass().getName());
		// SearchResult sr = (SearchResult) tmp;
		// Attributes at = sr.getAttributes();
		// System.out.println(at.get("cn"));
		// }
		// System.out.println("Done "+ne.hasMore());
		return ne.hasMore();
	}

	/**
	 * Modify the attribute in the ldap directory for the given string.
	 * 
	 * @param mods
	 *            add all the entry in to the ModificationItem
	 * @param string
	 *            the string (dn) value
	 */
	public void modifyTest(ModificationItem[] mods, String string) throws NamingException {
		dirContext.modifyAttributes(string, mods);
	}

	/**
	 * Create the attribute in the ldap directory for the given string.
	 * 
	 * @param basicattributes
	 *            add all the entry in to the basicattribute
	 * @param string
	 *            the string (dn) value
	 */
	public void createTest(BasicAttributes basicattributes, String string) throws NamingException {
		// DirContext dc = //TODO perhaps return this?
		dirContext.createSubcontext(string, basicattributes);
	}

	/**
	 * Delete the attribute from the ldap directory.
	 * 
	 * @param string
	 *            the string (dn) value
	 */
	public void deleteTest(String string) throws NamingException {
		dirContext.destroySubcontext(string);
	}
}